﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Management.Automation;
using System.Text.RegularExpressions;

namespace BELT
{
    [Cmdlet("Select", "BrowserElement")]
    public class SelectBrowserElementCommand : Cmdlet
    {
        private string _id = null;
        private string _name = null;
        private string _innertext = null;
        private string _value = null;
        //private string _class = null;
        private string _tagname = null;
        private string _type = null;
        private string _alt = null;
        private string _href = null;
        private string _src = null;
        private Object _selectIE = null;
        //private List<Object> iframes = new List<object>();
        //private Hashtable iframeHash = new Hashtable();

        #region Properties
        //[Parameter(ValueFromPipeline = false)]
        //public SwitchParameter FollowIFrame { set; get; }
        [Parameter(Mandatory = false, ValueFromPipeline = true)]
        public Object IEBrowser
        {
            get {
                return _selectIE;
            }
            set
            {
                _selectIE = value;
            }
        }
        [Parameter(Mandatory=false,ValueFromPipeline=false)]
        public string ID {
            get {
                return _id;
            }
            set {
                _id = value;
            }
        }
        [Parameter(Mandatory = false, ValueFromPipeline = false)]
        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
            }
        }
        [Parameter(Mandatory = false, ValueFromPipeline = false, Position = 1)]
        public string InnerText
        {
            get
            {
                return _innertext;
            }
            set
            {
                _innertext = value;
            }
        }
        [Parameter(Mandatory = false, ValueFromPipeline = false)]
        public string Value
        {
            get
            {
                return _value;
            }
            set
            {
                _value = value;
            }
        }
        [Parameter(Mandatory = false, ValueFromPipeline = false)]
        public string Alt
        {
            get
            {
                return _alt;
            }
            set
            {
                _alt = value;
            }
        }
        [Parameter(Mandatory = false, ValueFromPipeline = false)]
        public string Src
        {
            get
            {
                return _src;
            }
            set
            {
                _src = value;
            }
        }
        [Parameter(Mandatory = false, ValueFromPipeline = false)]
        public string Href
        {
            get
            {
                return _href;
            }
            set
            {
                _href = value;
            }
        }
        /*
        [Parameter(Mandatory = false, ValueFromPipeline = false)]
        public string Class
        {
            get
            {
                return _class;
            }
            set
            {
                _class = value;
            }
        }
        */
        [Parameter(Mandatory = false, ValueFromPipeline = false)]
        public string Type
        {
            get
            {
                return _type;
            }
            set
            {
                _type = value;
            }
        }
        [Parameter(Mandatory = false, Position=0, ValueFromPipeline = false)]
        public string TagName
        {
            get
            {
                return _tagname;
            }
            set
            {
                _tagname = value;
            }
        }
        #endregion

        protected override void BeginProcessing()
        {
            base.BeginProcessing();
            if (_selectIE == null)
            {
                _selectIE = NewIEBrowserCommand.IEHandle;
            }
            else {
                PSObject psObj = (PSObject)_selectIE;
                _selectIE = psObj.BaseObject;
            }
            if (_selectIE == null) {
                this.ThrowTerminatingError(new ErrorRecord(new EntryPointNotFoundException("No IEBrowser object specified."), "E001", ErrorCategory.ObjectNotFound, null));
            }
        }
        protected override void ProcessRecord()
        {
            base.ProcessRecord();
            DoSearch();
        }
        protected override void EndProcessing()
        {
            base.EndProcessing();
            _selectIE = null;
        }
        protected override void StopProcessing()
        {
            base.StopProcessing();
            _selectIE = null;
        }
        void DoSearch() {
            SearchEntity(_selectIE);
            /*
            if (FollowIFrame.IsPresent) {
                while (iframes.Count > 0) {
                    Object ifr = iframes[0];
                    iframes.RemoveAt(0);
                    SearchEntity(ifr);
                }
            }
            */
        }
        void SearchEntity(Object rootObj) {
            Type rootType = rootObj.GetType();
            Object docObj = rootType.InvokeMember("document", System.Reflection.BindingFlags.GetProperty, null, rootObj, null);
            Type docType = docObj.GetType();
            /*
            if (FollowIFrame.IsPresent) {
                Object ifrs = docType.InvokeMember("getElementsByTagName", System.Reflection.BindingFlags.InvokeMethod, null, docObj, new object[1] { "iframe" });
                foreach (Object ifObj in (IEnumerable)ifrs) {
                    Type ifType = ifObj.GetType();
                    Object uid = ifType.InvokeMember("uniqueID", System.Reflection.BindingFlags.GetProperty, null, ifObj, null);
                    if (! iframeHash.ContainsKey(uid.ToString()))
                    {
                        WriteWarning("IFrame: " + uid.ToString());
                        iframeHash[uid.ToString()] = 1;
                        iframes.Add(ifObj);
                    }
                }
            }
            */
            if (_id != null)
            {
                Object objOfID = docType.InvokeMember("getElementById", System.Reflection.BindingFlags.InvokeMethod, null, docObj, new object[1] { _id });
                WriteObject(objOfID);
                return;
            }
            Object allObj = docType.InvokeMember("all", System.Reflection.BindingFlags.GetProperty, null, docObj, null);
            int objCount = 0;
            foreach (Object obj in (IEnumerable)allObj)
            {
                objCount++;
                if (!Compare(obj, "tagName", _tagname)) continue;
                //WriteWarning("pass tagname");
                if (!Compare(obj, "name", _name)) continue;
                //WriteWarning("pass name");
                if (!Compare(obj, "type", _type)) continue;
                //WriteWarning("pass type");
                if (!Compare(obj, "value", _value)) continue;
                //WriteWarning("pass value");
                if (!Compare(obj, "href", _href)) continue;
                //WriteWarning("pass href");
                if (!Compare(obj, "alt", _alt)) continue;
                //WriteWarning("pass alt");
                if (!Compare(obj, "src", _src)) continue;
                //WriteWarning("pass src");
                if (!Compare(obj, "innerText", _innertext)) continue;
                //WriteWarning("pass innertext");
                WriteObject(obj);
            }
            //WriteWarning("Total: " + objCount);
        }
        bool Compare(Object obj, string propertyName, string expectedValue) {
            if (expectedValue == null) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            Type objType = obj.GetType();
            Object propertyValue = null;
            try
            {
                propertyValue = objType.InvokeMember(propertyName, System.Reflection.BindingFlags.GetProperty, null, obj, null);
            }
            catch(Exception e){
                //WriteWarning(propertyName + " not found: " + e.Message);
                return false;
            }
            
            if (propertyValue == null) {
                return false;
            }
            //WriteWarning(propertyName + ": " + propertyValue.ToString() + " <-> " + expectedValue);
            expectedValue = "^" + expectedValue.Replace("*", ".*") + "$";
            //WriteWarning(expectedValue);
            Regex regex = new Regex(expectedValue, RegexOptions.IgnoreCase);
            Match match = regex.Match(propertyValue.ToString());
            if (match.Success)
            {
                return true;
            }
            else {
                return false;
            }
        }
    }
}
